package com.qf.chinatelcon.apigateway.filter;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.qf.chinatelcon.apigateway.feign.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;


import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

@Component
public class IdentityFilter extends ZuulFilter {

    private CacheService cacheService;

    @Autowired
    public void setCacheService(CacheService cacheService) {
        this.cacheService = cacheService;
    }

    private LoadingCache loadingCache;

    @PostConstruct
    public void init() {
        //如果缓存中没有数据，从什么地方加载数据
        loadingCache = CacheBuilder.newBuilder().expireAfterWrite(60, TimeUnit.SECONDS).build(new CacheLoader<String, Boolean>() {
            @Override
            public Boolean load(String s) throws Exception {
                Boolean setNx = cacheService.setNx(s, "suibianxie", 120);
                return setNx;
            }
        });

    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 13;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();
        return context.sendZuulResponse();
    }


    @Override
    public Object run() throws ZuulException {
        //获取到签名就去缓存中查找就可以了
        //如果存在就返回false不存在就返回true这样就可以用到setnx这个方法，没有就存入，有的话就返回true
        //到那时我们也不需要每次都查询缓存，我们应该在本地服务器中存放着一份临时数据，这样的话，我们就不需要每次都查询缓存了
        //我们前边有时间戳的检验，所以设置60s就够了，但是我们在前边时间的校验中设置的是前后个60s所以我们在这就应该写120s
        //当前便给我们返回true的时候我们就应该拦截操作
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        String sign = request.getParameter("sign");//因为用户的签名是不变的，所以我们可以把它当做唯一标识
        Boolean a = false;
        try {
            a = (Boolean) loadingCache.get(sign);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        if (!a) {
            //就证明数据已经存在缓存中，那麽我们就直接进行拦截
            context.setSendZuulResponse(false);
            context.setResponseBody("请不要频繁发送请求");
            context.addZuulResponseHeader("content-Type", "text/html;charset=utf-8");
        } else {
            loadingCache.put(sign, false);//改成false 的原因是因为我们第一次是允许通过的，第二次就应该改成false不允许通过
        }
        return null;
    }
}
